package com.yuuko.yuukoapi.project.system.controller

import cn.dev33.satoken.stp.StpUtil
import com.yuuko.yuukoapi.common.exception.BizException
import com.yuuko.yuukoapi.common.exception.ErrorCode
import com.yuuko.yuukoapi.common.response.AjaxResult
import com.yuuko.yuukoapi.common.response.None
import com.yuuko.yuukoapi.model.system.Menus
import com.yuuko.yuukoapi.model.system.by
import com.yuuko.yuukoapi.model.system.dto.MenuUpdateInput
import com.yuuko.yuukoapi.repository.system.MenusRepository
import org.babyfish.jimmer.sql.kt.fetcher.newFetcher
import org.springframework.web.bind.annotation.DeleteMapping
import org.springframework.web.bind.annotation.GetMapping
import org.springframework.web.bind.annotation.PathVariable
import org.springframework.web.bind.annotation.PostMapping
import org.springframework.web.bind.annotation.PutMapping
import org.springframework.web.bind.annotation.RequestBody
import org.springframework.web.bind.annotation.RequestMapping
import org.springframework.web.bind.annotation.RequestParam
import org.springframework.web.bind.annotation.RestController
import java.awt.Menu

@RestController
@RequestMapping("/system/menu")
class MenusController(
    val menusRepository: MenusRepository
) {
    @GetMapping("/all")
    fun all(): AjaxResult<List<Menus>> {
        val userId = StpUtil.getLoginIdAsString()
        val result = menusRepository.findTreeByUserId(userId)
        return AjaxResult.ok(result)
    }

    @GetMapping("/list")
    fun getMenuList(): AjaxResult<List<Menus>> {
        val result = menusRepository.findAllTree()
        return AjaxResult.ok(result)
    }

    @GetMapping("/name-exists")
    fun isMenuNameExists(
        @RequestParam("name") name: String?,
        @RequestParam("id") id: String?
    ): AjaxResult<Boolean> {
        val result = menusRepository.existsOtherByName(name, id)
        return AjaxResult.ok(result)
    }

    @GetMapping("/path-exists")
    fun isMenuPathExists(
        @RequestParam("path") path: String?,
        @RequestParam("id") id: String?
    ): AjaxResult<Boolean> {
        val result = menusRepository.existsOtherByPath(path, id)
        return AjaxResult.ok(result)
    }

    @PostMapping
    fun createMenu(@RequestBody input: MenuUpdateInput): AjaxResult<None?> {
        menusRepository.save(input)
        return AjaxResult.ok()
    }

    @PutMapping("/{id}")
    fun updateMenu(@PathVariable id: String, @RequestBody input: MenuUpdateInput): AjaxResult<None?> {
        menusRepository.save(input.toEntity { this.id = id })
        return AjaxResult.ok()
    }

    @DeleteMapping("/{id}")
    fun deleteMenu(@PathVariable id: String): AjaxResult<None?> {
        val childNum = menusRepository.findNullable(id, newFetcher(Menus::class).by {
            children()
        })?.children?.size
        if (childNum == null) throw BizException(ErrorCode.ID_NOT_FOUND)
        if (childNum > 0) throw BizException(ErrorCode.HAS_CHILDREN)
        menusRepository.deleteById(id)
        return AjaxResult.ok()
    }


}